#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System;
using ZO.SmartCore.Security.Cryptography;
using ZO.SmartCore.Text;
using ZO.SmartCore.Xml;
using ZO.SmartMessenger.Plugins;
using ArgumentException= ZO.SmartCore.Core.ArgumentException;

#endregion

namespace ZO.SmartMessenger.UI
{
    /// <summary>
    /// Represent an account in Messenger
    /// </summary>
    internal class Account : Element
    {

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Account"/> class.
        /// </summary>
        public Account()
            : base("account")
        {
        }

        #endregion

        #region Destructor

        #endregion

        #region Fields

        private bool _Login;

        #endregion

        #region Events

        #endregion

        #region Operators

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="Account"/> is currently login.
        /// </summary>
        /// <value><c>true</c> if login; otherwise, <c>false</c>.</value>
        public bool Login
        {
            get
            {
                return _Login;
            }
            set
            {
                _Login = value;
            }
        }


        /// <summary>
        /// Gets or sets the protocol.
        /// </summary>
        /// <value>The protocol.</value>
        public ProtocolPlugin Protocol
        {
            get
            {
                Element protocol = SelectSingleElement("protocol");

                if (protocol == null)
                {
                    return null;
                }


                string id = protocol.GetAttribute("id");

                if (!String.IsNullOrEmpty(id))
                {
                    try
                    {

                        Guid guid = new Guid(id);
                        if (MessengerHelper.ProtocolPlugins.Contains(guid))
                        {
                            return MessengerHelper.ProtocolPlugins[guid];
                        }
                    }
                    catch (ArgumentException) { return null; }
                    catch (FormatException) { return null; }
                    catch (OverflowException) { return null; }
                }

                return null;

            }
            set
            {

                Element protocol = SelectSingleElement("protocol");

                if (protocol == null)
                {
                    protocol = new Element("protocol");
                    this.AddChildElement(protocol);
                }


                protocol.Attributes["id"] = value.ID.ToString();

                protocol.Attributes["name"] = value.Name;
            }
        }


        /// <summary>
        /// Gets or sets the name of the account.
        /// </summary>
        /// <value>The name of the account.</value>
        public string AccountName
        {
            get
            {
                return this.Attributes["name"];
            }
            set
            {
                this.Attributes["name"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the user.
        /// </summary>
        /// <value>The name of the user.</value>
        public string UserName
        {
            get
            {
                Element user = this["username"];

                if (user == null)
                {
                    return null;
                }

                return user.Value;
            }
            set
            {
                Element user = this["username"];

                if (user == null)
                {
                    user = this.AddChildElement("username");
                }
                user.Value = value;
            }
        }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        /// <value>The password.</value>
        public string Password
        {
            get
            {
                Element pass = this["password"];

                if (pass == null)
                {
                    return null;
                }

                if (!String.IsNullOrEmpty(AccountName))
                {
                    CDATA data = (CDATA)pass.FindChild(SmartCore.Xml.NodeType.CDATA);

                    if (data != null)
                    {
                        string text = data.Value;

                        if (!String.IsNullOrEmpty(text))
                        {
                            return Cryptographer.DecryptSymmetric(this.AccountName, text);
                        }
                    }
                }

                return null;
            }
            set
            {
                if (this.RememberPassword)
                {
                    Element pass = this["password"];

                    if (pass == null)
                    {
                        pass = this.AddChildElement("password");
                    }
                    if (!String.IsNullOrEmpty(value) & !String.IsNullOrEmpty(this.AccountName))
                    {
                        //string key = Cryptographer.CreateHash("secret", SmartCore.Text.CharacterEncoding.UTF8);
                        string text = Cryptographer.EncryptSymmetric(this.AccountName, value, CharacterEncoding.UTF8);

                        //string value2 = Cryptographer.DecryptSymmetric(this.AccountName, text, CharacterEncoding.UTF8);
                        pass.AddChild(new CDATA(text));
                    }
                }

            }
        }


        /// <summary>
        /// Gets or sets a value indicating whether [remember password].
        /// </summary>
        /// <value><c>true</c> if [remember password]; otherwise, <c>false</c>.</value>
        public bool RememberPassword
        {
            get
            {
                Element element = this["remember"];


                if (element == null)
                {
                    return false;
                }

                bool ret;

                Boolean.TryParse(element.Value, out ret);

                return ret;


            }
            set
            {
                Element element = this["remember"];

                if (element == null)
                {
                    element = this.AddChildElement("remember");
                }
                element.Value = value.ToString();

            }
        }


        /// <summary>
        /// Gets or sets a value indicating whether [auto login].
        /// </summary>
        /// <value><c>true</c> if [auto login]; otherwise, <c>false</c>.</value>
        public bool AutoLogin
        {
            get
            {
                Element element = this["autologin"];


                if (element == null)
                {
                    return false;
                }

                bool ret;

                Boolean.TryParse(element.Value, out ret);

                return ret;


            }
            set
            {
                Element element = this["autologin"];

                if (element == null)
                {
                    element = this.AddChildElement("autologin");
                }
                element.Value = value.ToString();

            }
        }

        #endregion

        #region Methods

        #endregion
    }
}
